package spring.cloud.tasks.client.item_task_processor;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

@Slf4j
public class TaskProcessingThread extends Thread {
    public TaskProcessingThread(TaskProcessingThreadContext taskProcessingThreadContext) {
        this.taskProcessingThreadContext = taskProcessingThreadContext;
    }

    private TaskProcessingThreadContext taskProcessingThreadContext;
    @Setter
    @Getter
    volatile boolean destroy = false;
    @Setter
    @Getter
    volatile boolean needDestroyTaskDatas = false;

    public void run() {
        try {

            while (true) {
                while (true) {
                    //destroy 是线程必须清理,needDestroyTaskDatas是暂时清理数据 稍后进行数据处理。
                    //时间差...n ns
                    if (destroy || taskProcessingThreadContext.destroy) {
                        destroy = true;
                        return;
                    }
                    //
                    if (needDestroyTaskDatas) {
                        TimeUnit.SECONDS.sleep(1);
                        continue;
                    }
                    try {
                        if (!getTaskDataAndExecuteTaskOrNeedWaitTaskDatas()) {
                            //需要等
                            break;
                        }
                    } catch (InterruptedException e) {
                        return;
                    }

                }//inner layer while
                TimeUnit.SECONDS.sleep(1);
                int taskDataSize = taskProcessingThreadContext.getTaskDataIdsFromDb();
                if (taskDataSize > 0) {
                    continue;//立即去处理数据
                } else {
                    if (!taskProcessingThreadContext.destroy && taskProcessingThreadContext.taskProcessor.isContinueWhenNoTaskDataIdList()) {
                        taskProcessingThreadContext.isSleeping = true;
                        TimeUnit.SECONDS.sleep(1);
                        taskProcessingThreadContext.isSleeping = false;
                    }
                }

            }// outer layer while
        } catch (Throwable e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * @return true get task datas ok,不考虑是否执行成功,false need wait task datas
     * @throws InterruptedException
     */
    private boolean getTaskDataAndExecuteTaskOrNeedWaitTaskDatas() throws InterruptedException {
        //load task from here
        Object taskDataId;
        try {
            taskProcessingThreadContext.getTaskDatasSemaphore.acquire();
            //时间差...n ns,avoid heavy lock lose time to update status start,so must recheck
            if (destroy || taskProcessingThreadContext.destroy) {
                destroy = true;
                throw new InterruptedException();//return;
            }
            //avoid heavy lock lose time to update status end
            if (taskProcessingThreadContext.multipleTaskDataProcessor == false) {
                taskDataId = taskProcessingThreadContext.getTaskDataId();
            } else {
                taskDataId = taskProcessingThreadContext.getTaskDataIds();
            }
        } finally {
            taskProcessingThreadContext.getTaskDatasSemaphore.release();
        }
        if (taskDataId == null) {
            TimeUnit.SECONDS.sleep(1);
            return false; //跳出内层循环,false NeedWaitDatas
        }
        long startTime = taskProcessingThreadContext.taskProcessor.zooKeeperItemTaskDataManager.zooKeeperCurrentTimeMillis();
        try {
            //SingleTaskDataProcessor
            if (!taskProcessingThreadContext.multipleTaskDataProcessor) {
                if (taskProcessingThreadContext.$taskProcessor$.execute(taskDataId) == true) {
                    taskProcessingThreadContext.addTaskSuccessNum(1, taskProcessingThreadContext.taskProcessor.zooKeeperItemTaskDataManager.zooKeeperCurrentTimeMillis() - startTime);
                } else {
                    taskProcessingThreadContext.addTaskFailNum(1, taskProcessingThreadContext.taskProcessor.zooKeeperItemTaskDataManager.zooKeeperCurrentTimeMillis() - startTime);
                }
            } else {//MultipleTaskDataProcessor
                if (taskProcessingThreadContext.$taskProcessor$.execute((Object[]) taskDataId) == true) {
                    taskProcessingThreadContext.addTaskSuccessNum(((Object[]) taskDataId).length, taskProcessingThreadContext.taskProcessor.zooKeeperItemTaskDataManager.zooKeeperCurrentTimeMillis() - startTime);
                } else {
                    taskProcessingThreadContext.addTaskFailNum(((Object[]) taskDataId).length, taskProcessingThreadContext.taskProcessor.zooKeeperItemTaskDataManager.zooKeeperCurrentTimeMillis() - startTime);
                }
            }
        } catch (Throwable ex) {
            if (!taskProcessingThreadContext.multipleTaskDataProcessor) {
                taskProcessingThreadContext.addTaskFailNum(1, taskProcessingThreadContext.taskProcessor.zooKeeperItemTaskDataManager.zooKeeperCurrentTimeMillis() - startTime);
            } else {
                taskProcessingThreadContext.addTaskFailNum(((Object[]) taskDataId).length, taskProcessingThreadContext.taskProcessor.zooKeeperItemTaskDataManager.zooKeeperCurrentTimeMillis() - startTime);
            }
            log.warn("TaskDataId :" + taskDataId + " ", ex);
        }
        return true;//get task datas ok,不考虑是否执行成功
    }
}
